/*
 * 文 件 名:  AceStringUtils.java
 * 版    权:  深圳埃思欧纳信息咨询有限公司版权所有. YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 修 改 人:  Administrator
 * 修改时间:  2010-3-18
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.common.utils;

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

/**
 * <字符串工具> <主要处理字符类型常用方法>
 * 
 * @author Eric.Zhang
 * @version [Aceona2.0, 2010-3-18]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class StringUtil
{
	/**
	 * 判断对象是否为空，为空返回true，反之返回false
	 * <功能详细描述>
	 * @param paramObject
	 * @return
	 * 
	 * @return boolean [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static boolean isNullOrEmpty(Object paramObject)
	{
	    return ((paramObject == null) || ("".equals(paramObject.toString().trim()))); 
	}

    /**
     * 判断对象是否为空，不为空返回true，反之返回false
     * <功能详细描述>
     * @param paramObject
     * @return
     * 
     * @return boolean [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
	public static boolean isNotNullAndEmpty(Object paramObject) 
	{
	    return (!(isNullOrEmpty(paramObject))); 
	}
	
	/**
	 * 处理字符串值为null的情况，如果字符串为null，则返回""；否则，返回原字符串；
	 * @param obj 字符串对象
	 * @return 处理结果
	 */
	public static String null2Empty(String obj) 
	{
		String ret = obj==null ? "":obj;
		return ret;
	}

	/**    
     * 获取字符串长度，中文字符算2个字节，中文格式的标点符号算1个字节.
     * <功能详细描述>
     * @param str
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    private static int getStrLen(String str)
    {
        int count=0;
        String regEx = "[\\u4e00-\\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        while(m.find())count++;
        return str.length()+count;
     }
    
    /***
	 * 截取字符串长度，中文字符算2个字节，去掉截一半的汉字
	 * @param param 原字符串
	 * @param num 限制的长度
	 * @return
	 */
	public static String limitStrLengthTag(String param,int num)
    {
		if (null == param || "".equals(param))
		{
			return "";
		}
		int strlen = getStrLen(param);
		if (strlen <= num)
		{
			return param;
		}
		char[] b = param.toCharArray();
		String regEx = "[\\u4e00-\\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        StringBuffer sb = new StringBuffer("");
        int count = 0;
		for (int i = 0;i < num;i++)
		{
			Matcher m = p.matcher(b[count]+"");
			
			if(m.find())
			{
				i++;
				if (i >= num)
				{
					continue;
				}
			}
			sb.append(b[count]);
			count++;
		}
        return sb.toString() + "...";
    }
	
    /**
	 * 截取字符串，中文字符和中文格式的标点符号都算2个字节，保留截一半的汉字
	 * <功能详细描述>
	 * @param s
	 * @param length
	 * @return
	 * 
	 * @return String [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static String splitUnicodeString(String s, int length)
	{   
	    try
	    {
            byte[] bytes = s.getBytes("Unicode");
            System.out.println(bytes);
            int n = 0; // 表示当前的字节数   
            int i = 2; // 要截取的字节数，从第3个字节开始   
            for (; i < bytes.length && n < length; i++){   
                // 奇数位置，如3、5、7等，为UCS2编码中两个字节的第二个字节   
                if (i % 2 == 1){   
                    n++; // 在UCS2第二个字节时n加1   
                }   
                else{   
                    // 当UCS2编码的第一个字节不等于0时，该UCS2字符为汉字，一个汉字算两个字节   
                    if (bytes[i] != 0){   
                        n++;   
                    }   
                }   
                   
            }   
            // 如果i为奇数时，处理成偶数   
            /*if (i % 2 == 1){  
                // 该UCS2字符是汉字时，去掉这个截一半的汉字  
                if (bytes[i - 1] != 0)  
                    i = i - 1;  
                // 该UCS2字符是字母或数字，则保留该字符  
                else  
                    i = i + 1;  
            }*/  
            //将截一半的汉字要保留   
            if (i % 2 == 1){   
             i = i + 1;   
            }   
            return new String(bytes, 0, i, "Unicode");
        }
        catch (UnsupportedEncodingException e)
        {
            return s.substring(0,length);
        }   
    } 
	
	/**
	 * 根据编码格式获取字符串长度
	 * <功能详细描述>
	 * @param str
	 * @return
	 * 
	 * @return int [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	 public static int getStrLenByEncoding(String paramString, String encoding) 
	 {
		  int length = 0;
	      try 
	      {
	    	  if (StringUtil.isNotNullAndEmpty(paramString)) 
	    	  {
	    		  if (StringUtil.isNotNullAndEmpty(encoding))
	    		  {
	    			  // UTF-8格式时一个中文字符和中文标点符号占3个字节;
		    		  // GBK和GB2312格式时一个中文字符和中文标点符号占2个字节
		    		  if (encoding.equalsIgnoreCase("UTF-8") || encoding.equalsIgnoreCase("GBK") || encoding.equalsIgnoreCase("GB2312"))
		    		  {
		    			  length = paramString.getBytes(encoding).length; 
					  }
				  }
	    		  else {
	    			  // 直接调用string的length方法则一个中文字符和中文标点符号占1个字节
	    			  length = paramString.length(); // 12
				  }
			   }
		   } catch (UnsupportedEncodingException e) 
		   {
			   e.printStackTrace();
		   }
		  return length;
	 }
	 
	/**
	 * 对少于给定位数的字符串进行左补位处理
	 * <功能详细描述>
	 * @param paramString 主字符串(待补位字符串)
	 * @param paramInt 字符串目标长度
	 * @param paramChar 补位字符
	 * @return
	 * 
	 * @return String [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static String padLeft(String paramString, int paramInt, char paramChar)
	{
		while (paramInt > paramString.length()) {
			paramString = paramChar + paramString ;
		}
		return paramString.substring(0, paramInt);
	}
	
	/**
	 * 对少于给定位数的字符串进行右补位处理
	 * <功能详细描述>
	 * @param paramString 主字符串(待补位字符串)
	 * @param paramInt 字符串目标长度
	 * @param paramChar 补位字符
	 * @return
	 * 
	 * @return String [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static String padRight(String paramString, int paramInt, char paramChar)
	{
		while (paramInt > paramString.length()) {
			paramString += paramChar;
		}
		return paramString.substring(0,paramInt);
	}
	
	/**
	 * 取消字符串中的多余空格符号
	 * @param obj 字符串
	 * @return 处理空格后的字符串
	 */
	public static String atrim(String obj)
	{
		String ret = null;
		if (obj==null){
			ret = null;
		}else{
			ret = obj.trim();
		}
		return ret;
	}
	
	/**
	 * 字符串填充函数
	 * @param val 字符串值
	 * @param s 填充字符
	 * @param len 长度
	 * @return
	 */
	public static String fillString(String val,String s,int len) 
	{
		String ret = null;
		if (val==null || s==null) return null;
		int l = val.length();
		String pre = ""; 
		for (int i = 0; i < len - l; i++) 
		{
			pre += s;
		} 
		ret = pre + val; 
		return ret;
	}
	
	/**
	 * 字符 + 整数， 生成新的字符串
	 * @param c 字符
	 * @param skip 间隔
	 * @return
	 */
	public static String addAscii(char c, int skip) 
	{
		String ret = null;
		int _c = (int)c;
		char _char = (char) (_c + skip);
		ret = String.valueOf(_char);
		return ret;
	}
	
    /**
     * 将map转换为字符串形式
     * 
     * @param map
     * @return
     */
    public static String mapToStr(Map map)
    {
        StringBuilder str = new StringBuilder();
        if (map == null || map.isEmpty())
        {
            return null;
        }

        str.append("{\n");
        Iterator it = map.entrySet().iterator();

        for (int i = map.size() - 1; it.hasNext(); i--)
        {
            Map.Entry entry = (Map.Entry) it.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
            String strTmp = null;
            if (val != null)
            {
                strTmp = val.toString();
                if (val instanceof Object[])
                {
                    strTmp = arrayToStr((Object[]) val);
                }
                else if (val instanceof int[])
                {
                    strTmp = arrayToStr((int[]) val);
                }
            }

            str.append("\t\t" + key + ": \t" + strTmp + (i == 0 ? "" : " \n"));
        }

        str.append("\n\t}");
        return str.toString();
    }

    /**
     * 将Object数组转换为字符串形式
     * 
     * @param arr Object[]
     * @return String
     */
    public static String arrayToStr(Object[] arr)
    {
        StringBuilder str = new StringBuilder();

        if (arr == null || arr.length < 1)
        {
            return null;
        }

        str.append("{");
        for (int i = 0; i < arr.length; i++)
        {
            str.append(arr[i] + ((i + 1) == arr.length ? "" : ", "));
        }
        str.append("}");

        return str.toString();
    }

    /**
     * 将Object二维数组转换为字符串形式
     * 
     * @param arr Object[][]
     * @return String
     */
    public static String arraysToStr(Object[][] arr)
    {
        StringBuilder str = new StringBuilder();

        if (arr == null || arr.length < 1)
        {
            return null;
        }

        str.append("{\n");
        for (int i = 0; i < arr.length; i++)
        {
            str.append("{");
            if (arr[i] == null)
            {
                continue;
            }

            for (int j = 0; j < arr[i].length; j++)
            {
                str.append(arr[i][j] + ((j + 1) == arr[i].length ? "" : ", "));
            }
            str.append("}" + ((i + 1) == arr.length ? "" : ", "));
        }
        str.append("\n}");

        return str.toString();
    }

    /**
     * 将int数组转换为字符串形式
     * 
     * @param arr int[]
     * @return
     */
    public static String arrayToStr(int[] arr)
    {
        StringBuilder str = new StringBuilder();

        if (arr == null || arr.length < 1)
        {
            return null;
        }

        str.append("{");
        for (int i = 0; i < arr.length; i++)
        {
            str.append(arr[i] + ((i + 1) == arr.length ? "" : ", "));
        }
        str.append("}");

        return str.toString();
    }

   /**
     * <处理特殊字符> <在单引号时加\,没转义的做转义>
     * @param str
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String escapeSpecialString(String str)
    {
        return escapeSpecialStringStyleString(str, true);
    }

    /**
     * <p>
     * Worker method for the {@link #escapeJavaScript(String)} method.
     * </p>
     * 
     * @param str String to escape values in, may be null
     * @param escapeSingleQuotes escapes single quotes if <code>true</code>
     * @return the escaped string
     */
    private static String escapeSpecialStringStyleString(String str, boolean escapeSingleQuotes)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            StringWriter writer = new StringWriter(str.length() * 2);
            escapeSpecialStringStyleString(writer, str, escapeSingleQuotes);
            return writer.toString();
        }
        catch (IOException ioe)
        {
            // this should never ever happen while writing to a StringWriter
            ioe.printStackTrace();
            return null;
        }
    }

    /**
     * <p>
     * Worker method for the {@link #escapeJavaScript(String)} method.
     * </p>
     * 
     * @param out write to receieve the escaped string
     * @param str String to escape values in, may be null
     * @param escapeSingleQuote escapes single quotes if <code>true</code>
     * @throws IOException if an IOException occurs
     */
    private static void escapeSpecialStringStyleString(Writer out, String str, boolean escapeSingleQuote)
            throws IOException
    {
        if (out == null)
        {
            throw new IllegalArgumentException("The Writer must not be null");
        }
        if (str == null)
        {
            return;
        }
        int sz;
        sz = str.length();
        for (int i = 0; i < sz; i++)
        {
            char ch = str.charAt(i);

            // handle unicode
            // if (ch > 0xfff)
            // {
            // out.write("\\u" + hex(ch));
            // }
            // else if (ch > 0xff)
            // {
            // out.write("\\u0" + hex(ch));
            // }
            // else if (ch > 0x7f)
            // {
            // out.write("\\u00" + hex(ch));
            // }
            // else
            if (ch < 32)
            {
                switch (ch)
                {
                    case '\b':
                        out.write('\\');
                        out.write('b');
                        break;
                    case '\n':
                        out.write('\\');
                        out.write('n');
                        break;
                    case '\t':
                        out.write('\\');
                        out.write('t');
                        break;
                    case '\f':
                        out.write('\\');
                        out.write('f');
                        break;
                    case '\r':
                        out.write('\\');
                        out.write('r');
                        break;
                    default:
                        // if (ch > 0xf)
                        // {
                        // out.write("\\u00" + hex(ch));
                        // }
                        // else
                        // {
                        // out.write("\\u000" + hex(ch));
                        // }
                        break;
                }
            }
            else
            {
                switch (ch)
                {
                    case '\'':
                        if (escapeSingleQuote)
                        {
                            out.write('\\');
                        }
                        out.write('\'');
                        break;
                    case '"':
                        out.write('\\');
                        out.write('"');
                        break;
                    case '\\':
                        out.write('\\');
                        out.write('\\');
                        break;
                    case '/':
                        out.write('\\');
                        out.write('/');
                        break;
                    default:
                        out.write(ch);
                        break;
                }
            }
        }
    }

    /**
     * 将输入字符串变为html显示字符串,added by qinhairong
     */
    public static String convert2Html(String source)
    {
        String returnString = source;
        if (source == null || source.equals(""))
        {
            return "";
        }
        returnString = returnString.replaceAll("<", "&lt;");
        returnString = returnString.replaceAll(">", "&gt;");
        returnString = returnString.replaceAll(" ", "&nbsp;");
        returnString = returnString.replaceAll("\r\n", "<br/>");
        returnString = returnString.replaceAll("\"", "&quot;");
        // returnString = returnString.replaceAll( "", "&#039;");
        returnString = returnString.replaceAll(" ", "&nbsp;");
        returnString = returnString.replaceAll("\r", "<br/>");
        returnString = returnString.replaceAll("\n", "<br/>");
        returnString = returnString.replaceAll("&lt;br&gt;", "<br/>");

        return returnString;
    }

    /**
     * 把html字符串变成可编辑的输入ascii字符
     */

    
    public static String decodeHtml(String source)
    {
        String returnString = source;
        if (source == null || source.equals(""))
        {
            return "";
        }
//        returnString = returnString.replace("<br>", "\r\n");
//        returnString = returnString.replace("<br />", "\r\n");
//        returnString = returnString.replace("<br/>", "\r\n");
//        returnString = returnString.replace("<br&nbsp;/>", "\r\n");
        returnString = returnString.replace("\"", "\\\"");
        returnString = returnString.replace("'", "\'"); 
        returnString = returnString.replace("\n", " "); 
        return returnString;
    }
    
    public static String Html2Text(String inputString) { 
        String htmlStr = inputString; //含html标签的字符串 
            String textStr =""; 
      java.util.regex.Pattern p_script; 
      java.util.regex.Matcher m_script; 
      java.util.regex.Pattern p_style; 
      java.util.regex.Matcher m_style; 
      java.util.regex.Pattern p_html; 
      java.util.regex.Matcher m_html; 
   
      try { 
       String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>"; //定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script> } 
       String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>"; //定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style> } 
          String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式 
      
          p_script = Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE); 
          m_script = p_script.matcher(htmlStr); 
          htmlStr = m_script.replaceAll(""); //过滤script标签 

          p_style = Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE); 
          m_style = p_style.matcher(htmlStr); 
          htmlStr = m_style.replaceAll(""); //过滤style标签 
      
//          p_html = Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE); 
//          m_html = p_html.matcher(htmlStr); 
//          htmlStr = m_html.replaceAll(""); //过滤html标签 
      
       textStr = htmlStr; 
      
      }catch(Exception e) { 
               System.err.println("Html2Text: " + e.getMessage()); 
      } 
   
      return textStr;//返回文本字符串 
    } 

    /**
     * <防SQL注入 >
     * <功能详细描述>
     * @param str
     * @return [参数说明]
     * 
     * @return boolean [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static boolean sql_inj(String str) 
    {
    	String inj_str = "':and:exec:insert:select:delete:update:count:*:%:chr:mid:master:truncate:char:declare:;:or:-:+:,";
    	String inj_stra[] = inj_str.split(":");
	    for (int i=0 ; i < inj_stra.length ; i++ )
	    {
		    if (str.indexOf(inj_stra[i])!=-1)
		    {
		    	return true;
		    }
		}
	    return false;
    }
    
    //调试
    public static void main(String[] args)
    {
    	/**
    	 //字符串长度测试
		 String strString = "1a发";
		 int len = StringUtil.getStrLen(strString);
		 System.out.print(len);
		 
		//特殊字符\的处理
		String str = "sdfsdfaasdfasdfasdfasdfasdfasdf'   dfsagsdafasdf \'dsaf sdaf sdaf sadf ";
    	str = StringUtils.replace(str, "\\", "");
    	System.out.println(str);
    	System.out.println(StringEscapeUtils.escapeSql(str));
    	System.out.println(StringUtil.escapeSpecialString(str));
   	
	      //replace方法的使用	  
		  String strTest="Replace Region";   
		  System.out.println( strTest.replace( 'R','A' ) );
		  System.out.println( strTest.replaceFirst("Re", "Ra") );
		  System.out.println( strTest.replaceAll("Re", "Ra") ); 
		  System.out.println(StringUtils.replace(strTest, "R", "A"));
		  System.out.println(StringUtils.replaceOnce(strTest, "Re", "Ra"));
		  
		  String a = "我爱您，shotfu打算";
		System.out.print(getStrLen(a)); // 17
		getStrLenByEncoding(a,"");
		System.err.print(getStrLenByEncoding(a,"utf-8"));
		System.out.println(limitStrLengthTag(a,13)); // 我爱您，shotfu...
		System.out.println(splitUnicodeString(a,13)); // 我爱您，shotf
		*/
		// 将list先转为Object数组，再转为string
		List<String> paramNamesList = new ArrayList<String>();
		List<String> operatorsList = new ArrayList<String>();
		Map<String, Object> keyvalueMap = new HashMap<String, Object>();
		paramNamesList.add("id");
		paramNamesList.add("name");
		operatorsList.add("=");
		operatorsList.add("like");
		keyvalueMap.put("age", 25);
		// 将list转为String类型二维数组
		String[][] paramNames = new String[][] { paramNamesList.toArray(new String[] {}) };
		// 将list转为String类型一维数组
		String[] operators = operatorsList.toArray(new String[] {});
		// 将二维数组转为String
		String strParamName = arraysToStr(paramNames);
		// 将一维数组转为String
		String strOperator = arrayToStr(operators);
		// 将map转为String
		String strKeyValue = mapToStr(keyvalueMap);
		System.out.println("strParamName:"+strParamName+" :: " + "strOperator:"+strOperator+" :: "+"strKeyValue:"+strKeyValue);
    }

}
